$S.WindowManager = function(){
    return {
        put : function(win){
        	if(!this.cache) this.cache = [];
        	this.cache.add(win)
        },
        getAll : function(){
        	return this.cache;
        },
        remove : function(win){
        	this.cache.remove(win);
        },
        get : function(id){
        	if(!this.cache) return null;
        	var win = null;
        	for(var i = 0;i<this.cache.length;i++){
    			if(this.cache[i].id == id) {
	        		win = this.cache[i];
    				break;      			
        		}
        	}
        	return win;
        },
        getZindex: function(){
        	var zindex = 40;
        	var all = this.getAll();
            if(all)
        	for(var i = 0;i<all.length;i++){
        		var win = all[i];
        		var zd = win.wrap.getStyle('z-index');
        		zd = (zd =='auto') ? 0 : Number(zd);
        		if(zd > zindex) zindex = zd;       		
        	}
        	return Number(zindex);
        }
    };
}();
/**
 * @class Spark.Window
 * @extends Spark.Component
 * <p>窗口组件.
 * @author njq.niu@hand-china.com
 * @constructor
 * @param {Object} config 配置对象. 
 */
$S.Window = Ext.extend($S.ViewComponent,{
    focusCss:'w_fs',
	constructor: function(config) { 
		if($S.WindowManager.get(config.id))return;
        this.draggable = true;
        this.closeable = true;
        this.hasCloseBtn = true;
        this.autoCenter = true;
        this.modal = config.modal||true;
        this.className = config.className||'';
        this.cmps = {};
        $S.Window.superclass.constructor.call(this,config);
    },
    initComponent : function(config){
        var sf = this; 
        $S.WindowManager.put(sf);
        $S.Window.superclass.initComponent.call(this, config);
    	var windowTpl = new Ext.Template(sf.getTemplate(sf.title,sf.hasCloseBtn));
    	sf.width = 1*(sf.width||400);
        sf.wrap = windowTpl.insertFirst(document.body, {title:sf.title,className:sf.className,width:"width:"+1*(sf.width||400) + "px",height:sf.height ? ("height:" + 1*(sf.height)+ "px") : ""}, true);
    	sf.head = sf.wrap.child('div.s-dlg-head');
    	sf.body = sf.wrap.child('div.s-dlg-ct');
        sf.closeBtn = sf.wrap.child('div.s-dlg-close');
        if(this.autoCenter) sf.center();
        if(sf.url){
        	sf.showLoading();       
        	sf.load(sf.url,sf.params)
        }
    },
    processListener: function(ou){
    	$S.Window.superclass.processListener.call(this,ou);
    	if(this.closeBtn) {
    	   this.closeBtn[ou]("click", this.onCloseClick,  this);
    	}
    	if(!this.modal) this.wrap[ou]("click", this.toFront, this);
    	this.wrap[ou]("keydown", this.handleKeyDown,  this);
    	if(this.draggable)this.wrap[ou]('mousedown', this.onMouseDown,this);
    },
    initEvents : function(){
    	$S.Window.superclass.initEvents.call(this);
    	this.addEvents(
    	/**
         * @event close
         * 窗口关闭事件.
         * @param {Window} this 当前窗口.         * 
         */
    	'close',
    	/**
         * @event load
         * 窗口加载完毕.
         * @param {Window} this 当前窗口.
         */
    	'load');    	
    },
    handleKeyDown : function(e){
		var key = e.getKey();
		if(key == 9){ //tab
            
            var fk,lk,ck,cmp
            for(var k in this.cmps){
                cmp = this.cmps[k];
                if(!fk && cmp.focus){
                    fk=k;
                }
                lk=k;
                if(cmp.isFocused){
                    ck = k;
                }
            }
            if(e.shiftKey){
                var temp = lk;
                lk = fk;
                fk = temp;
            }
            
            if(ck==lk){
                e.stopEvent();
                if(cmp && cmp.blur)cmp.blur();
                this.cmps[fk].focus();
            }
        }else if(key == 27){//esc
			if(this.hasCloseBtn)this.close();
		}
    },
    center: function(){
    	var screenWidth = $S.getViewportWidth(),screenHeight = $S.getViewportHeight(),
            sl = document[Ext.isStrict?'documentElement':'body'].scrollLeft,
            st = document[Ext.isStrict?'documentElement':'body'].scrollTop,
            w = this.wrap.getWidth(),h = this.wrap.getHeight(),
    	    x = sl+Math.max((screenWidth - w)/2,0),
    	    y = st+Math.max((screenHeight - h)/2,0);
        this.wrap.moveTo(x,y);
        this.toFront();
    },
    getTemplate : function(hasHead,closeable) {
        return  [
            '<div class="s-dlg {className}" style="left:-10000px;top:-10000px;{width};{height}" tabIndex="-1" hidefocus>',
                hasHead ? '<div class="s-dlg-head s-dlg-draggable" unselectable="on">{title}</div>' : '',
                closeable ? '<div class="s-dlg-close" data-tooltip-type="tip" data-tooltip="关闭"></div>' : '',
                '<div class="s-dlg-ct"></div>',
            '</div>'
        ];
    },
    toFront : function(){ 
    	var myzindex = this.wrap.getStyle('z-index');
    	var zindex = $S.WindowManager.getZindex();
    	myzindex = (myzindex =='auto') ?  0 : Number(myzindex);
    	if(myzindex < zindex) {
	    	this.wrap.setStyle('z-index', zindex+5);
	    	if(this.modal) $S.Cover.cover(this.wrap,this.opacity);
    	}   	
    },
    onMouseDown : function(e){
    	var sf = this; 
    	sf.toFront();
        var v = Ext.fly(e.target).hasClass('s-dlg-draggable');
        if(v) {
            //if(sf.closeBtn && sf.closeBtn.contains(e.target))return;
            e.preventDefault();
        	var xy = sf.wrap.getXY();
        	sf.relativeX=xy[0]-e.getPageX();
    		sf.relativeY=xy[1]-e.getPageY();
    		sf.screenWidth = $S.getViewportWidth();
            sf.screenHeight = $S.getViewportHeight();
            if(!sf.proxy) sf.initProxy();
            sf.proxy.show();
            Ext.get(document.documentElement).on("mousemove", sf.onMouseMove, sf);
            Ext.get(document.documentElement).on("mouseup", sf.onMouseUp, sf);
        	sf.focus();
        }
        
    },
    onMouseUp : function(e){
    	var sf = this; 
    	Ext.get(document.documentElement).un("mousemove", sf.onMouseMove, sf);
    	Ext.get(document.documentElement).un("mouseup", sf.onMouseUp, sf);
    	if(sf.proxy){
    		sf.wrap.moveTo(sf.proxy.getX(),sf.proxy.getY());
	    	sf.proxy.hide();
    	}
    },
    onMouseMove : function(e){
    	e.stopEvent();
    	var sl = document[Ext.isStrict?'documentElement':'body'].scrollLeft;
    	var st = document[Ext.isStrict?'documentElement':'body'].scrollTop;
    	var sw = sl + this.screenWidth;
    	var sh = st + this.screenHeight;
    	var tx = e.getPageX()+this.relativeX;
    	var ty = e.getPageY()+this.relativeY;
    	if(tx<=sl) tx =sl;
    	if((tx+this.width)>= (sw-3)) tx = sw - this.width - 3;
    	if(ty<=st) ty =st;
    	if((ty+this.height)>= (sh-3)) ty = Math.max(sh - this.height,0);
    	this.proxy.moveTo(tx,ty);
    },
    showLoading : function(){
    	this.body.update('正在加载...');//TODO:多语言
    	this.body.setStyle('text-align','center');
    	this.body.setStyle('line-height',5);
    },
    clearLoading : function(){
    	this.body.update('');
    	this.body.setStyle('text-align','');
    	this.body.setStyle('line-height','');
    },
    initProxy : function(){
    	var sf = this; 
    	var p = '<DIV class="s-dlg-proxy" onselectstart="return false;" unselectable="on"><div class="s-dlg-proxy-body"></div></DIV>'
    	sf.proxy = Ext.get(Ext.DomHelper.insertFirst(Ext.getBody(),p));
    	var xy = sf.wrap.getXY();
    	sf.proxy.setWidth(sf.wrap.getWidth());
    	sf.proxy.setHeight(sf.wrap.getHeight());
    	sf.proxy.setLocation(xy[0], xy[1]);
    },
    onCloseClick : function(e){
        e.stopEvent();
    	this.close(); 	
    },
    hide : function(){
        this.wrap.hide();
        if(this.modal) $S.Cover.uncover(this.wrap)
    },
    show : function(){
        this.wrap.show();
        if(this.modal) $S.Cover.cover(this.wrap)
    },
    close : function(){
        if(this.closeable) {
            $S.WindowManager.remove(this);
            this.destroy(); 
            this.fireEvent('close', this)
        }else{
            $S.showWarningMessage('提示','当前窗口正在执行后台程序,无法关闭!',null, 350);
        }
    },
    destroy : function(){
//    	$S.focusWindow = null;
    	var wrap = this.wrap;
    	if(!wrap)return;
    	if(this.proxy) this.proxy.remove();
    	if(this.modal) $S.Cover.uncover(this.wrap);
        for(var key in this.cmps){
            var cmp = this.cmps[key];
            if(cmp.destroy){
                try{
                    cmp.destroy();
                }catch(e){
                    alert('销毁window出错: ' + e)
                }
            }
        }
    	$S.Window.superclass.destroy.call(this);
    	delete this.title;
    	delete this.head;
    	delete this.body;
        delete this.closeBtn;
        delete this.proxy;
        wrap.remove();
//        var sf = this;
//        setTimeout(function(){
//        	for(var key in sf.cmps){
//        		var cmp = sf.cmps[key];
//        		if(cmp.destroy){
//        			try{
//        				cmp.destroy();
//        			}catch(e){
//        				alert('销毁window出错: ' + e)
//        			}
//        		}
//        	}
//        },10)
    },
    /**
     * 窗口加载.
     * 
     * @param {String} url  加载的url
     * @param {Object} params  加载的参数
     */
    load : function(url,params){
//    	var cmps = $S.CmpManager.getAll();
//    	for(var key in cmps){
//    		this.oldcmps[key] = cmps[key];
//    	}
        var pa = params||{};
        pa['_sph'] = $S.viewHeight;
        pa['_spw'] = $S.viewWidth;
        pa['SUK'] = $S.suk;
    	Ext.Ajax.request({
			url: url,
            method: 'POST',
			params:pa||{},
		   	success: this.onLoad.createDelegate(this)
		});		
    },
    onLoad : function(response, options){
    	if(!this.body) return;
    	this.clearLoading();
    	var html = response.responseText;
    	var res
    	try {
            res = Ext.decode(response.responseText);
        }catch(e){}
        if(res && res.success == false){
        	if(res.error){
        		$S.manager.fireEvent('ajaxfailed', $S.manager, options.url,options.para,res);
                var st = res.error.stackTrace;
                st = (st) ? st.replaceAll('\r\n','</br>') : '';
                if(res.error.message) {
                    $S.showErrorMessage('错误', res.error.message+'</br>'+st,null,400);//TODO:多语言
                }else{
                    $S.showErrorMessage('错误', st,null,400);
                }   
            }
            return;
        }
    	var sf = this
    	this.body.update(html,true,function(){
//	    	var cmps = $S.CmpManager.getAll();
//	    	for(var key in cmps){
//	    		if(sf.oldcmps[key]==null){	    			
//	    			sf.cmps[key] = cmps[key];
//	    		}
//	    	}
	    	sf.fireEvent('load',sf);
            sf.focus();
    	},this);
    }
});
/**
 * 警告窗口
 * 
 * @param {String} title 标题
 * @param {String} msg 内容
 * @param {Function} callback 回调函数
 * @param {int} width 宽度
 * @return {Window} 窗口对象
 */
$S.showWarningMessage = function(title, msg,callback,width){
	return $S.showTypeMessage(title, msg, width,'s-dlg-warning',callback);
}
/**
 * 信息窗口
 * 
 * @param {String} title 标题
 * @param {String} msg 内容
 * @param {Function} callback 回调函数
 * @param {int} width 宽度
 * @return {Window} 窗口对象
 */
$S.showInfoMessage = function(title, msg,callback,width){
	return $S.showTypeMessage(title, msg, width, 's-dlg-info',callback);
}
/**
 * 错误窗口
 * 
 * @param {String} title 标题
 * @param {String} msg 内容
 * @param {Function} callback 回调函数
 * @param {int} width 宽度
 * @return {Window} 窗口对象
 */
$S.showErrorMessage = function(title,msg,callback,width){
	return $S.showTypeMessage(title, msg, width,'s-dlg-error',callback);
}

$S.showTypeMessage = function(title, content,width,cls,callback){
    var html = ['<div class="s-dlg-title">',title,'</div>','<div class="s-dlg-content">',content,'</div>']
	return $S.showOkWindow(cls,html.join(''), width||340,callback);	
} 
/**
 * 确定窗口.
 * 
 * @param {String} title 标题
 * @param {String} msg 内容
 * @param {Function} okfun 确定的callback
 * @param {Function} nofun 取消的callback
 * @param {int} width 宽度
 * @return {Window} 窗口对象
 */
$S.showConfirm = function(title, content, yesFun,noFun, width){
    var html = ['<div class="s-dlg-title">',title,'</div>','<div class="s-dlg-content">',content,'</div>']
    return $S.showYesNoWindow('s-dlg-confirm', html.join(''), yesFun,noFun, width||340);  	
}
/**
 * 带确定取消按钮的窗口.
 * 
 * @param {String} cls cls
 * @param {String} html html
 * @param {Function} yesfun 确定的callback
 * @param {Function} nofun 取消的callback
 * @param {int} width 宽度
 * @return {Window} 窗口对象
 */
$S.showYesNoWindow = function(cls, html, yesFun,noFun,width){
    var id = Ext.id();
    var wid = 's-win-' + id;
    var yid = 's-yes-'+id;
    var nid = 's-no-'+id;
    var cid = 's-cancle-'+id;
    var cmp = new $S.Window({id:wid,autoCenter:false, className:cls,width:width,hasCloseBtn:true});
    if(html){
        cmp.body.update(html+ '<div class="s-dlg-buttons">'+$S.Button.getTemplate(yid,'是', 70,'s-btn-b')+$S.Button.getTemplate(nid,'否',70)+'</div>',true,function(){
            cmp.center();
            var yesBtn = $(yid);
            var noBtn = $(nid);
            cmp.cmps[yid] = yesBtn;
            cmp.cmps[nid] = noBtn;
            yesBtn.on('click',function(){
            	if(yesFun)yesFun.call(this,cmp);
            });
            noBtn.on('click',function(){
            	if(noFun) {
                    noFun.call(this,cmp)
                }else{
                    cmp.close();                        
                }
            });
        });
    }
    return cmp;
}
/**
 * 带确定按钮的窗口.
 * 
 * @param {String} cls cls
 * @param {String} html html
 * @param {Function} okfun 确定的callback
 * @param {int} width 宽度
 * @return {Window} 窗口对象
 */
$S.showOkWindow = function(cls,html,width,callback){
    var id = Ext.id();
    var wid = 's-win-' + id;
    var oid = 's-ok-'+id;
	var btnhtml = $S.Button.getTemplate(oid,'确 定',70);
	var cmp = new $S.Window({id:wid,autoCenter:false,className:cls, width:width,hasCloseBtn:false});
	if(html){
		cmp.body.update(html+ '<div class="s-dlg-buttons">'+btnhtml+'</div>',true,function(){
            cmp.center();
			var btn = $(oid);
            cmp.cmps[oid] = btn;
            btn.on('click',function(){
                if(callback){
                    callback.call(this,cmp);
                }else{
                    cmp.close()                        
                }
            });
            btn.focus.defer(10,btn);
		});
	}
	return cmp;
}